#include "LogicExpression.h"

/*
LogicExpression::LogicExpression(void)
{
}


LogicExpression::~LogicExpression(void)
{
}
*/
VarExpression::VarExpression(string _name)
{
	type = 0;
	name = _name;
}
bool VarExpression::isEqual(LogicExpression* expr)
{
	return (expr->isVar() && name.compare(((VarExpression*)expr)->name) == 0 );
}
bool VarExpression::contain(LogicExpression* expr)
{
	return isEqual(expr);
}
LogicExpression* VarExpression::applySubstitute(Substitute* sub)
{
	int k = sub->find(this);
	if(k>-1)
	{
		return sub->getNewExpressionAt(k);
	}
	return this;
}

ConstExpression::ConstExpression(int _value)
{
	type = 1;
	//name = "";
	char* buffer=new char[10];
	buffer =  itoa(_value, buffer, 10);
	name = buffer;
	value = _value;
}
bool ConstExpression::isEqual(LogicExpression* expr)
{
	return (expr->isConst() && value == ((ConstExpression*)expr)->value);
}

FuncExpression::FuncExpression(string _name)
{
	type = 2;
	name = _name;
}
void FuncExpression::print()
{
	//cout <<"["<<type <<"]"<< name<<"(";
	cout<<name<<"(";
	for(int i=0;i<listArguments.size();i++)
	{
		if(i>0)
		{
			cout<<",";
		}
		listArguments[i]->print();
		
	}
	cout<<")";
}
void FuncExpression::setlistArguments(vector<LogicExpression*> _list)
{
	listArguments = _list;
}
bool FuncExpression::contain(LogicExpression* expr)
{
	return getArguments()->contain(expr);
}
LogicExpression* FuncExpression::getArguments()
{
	ListExpression* expr = new ListExpression(listArguments);
	return expr;
}
LogicExpression* FuncExpression::getSingleArgument()
{
	LogicExpression* expr;
	if(listArguments.size()>0)
	{
		expr = listArguments[0];
	}
	else
	{
		expr = new ListExpression(listArguments);
	}
	return expr;
}
LogicExpression* FuncExpression::applySubstitute(Substitute* sub)
{

	FuncExpression* newExpr = new FuncExpression(name);
	
	for(int i=0;i<listArguments.size();i++)
	{
		newExpr->listArguments.push_back( listArguments[i]->applySubstitute(sub));
	}
	if(newExpr->name.compare("DEC")==0)
	{
		LogicExpression* arg = newExpr->getSingleArgument();
		if(arg->isConst())
		{
			LogicExpression* val = new ConstExpression(((ConstExpression*)arg)->getValue()-1);
			return val;
		}
	}
	else if(newExpr->name.compare("INC")==0)
	{
		LogicExpression* arg = newExpr->getSingleArgument();
		if(arg->isConst())
		{
			LogicExpression* val = new ConstExpression(((ConstExpression*)arg)->getValue()+1);
			return val;
		}
	}
	return newExpr;
}
bool FuncExpression::isEqual(LogicExpression* expr)
{
	if(!expr->isFunc())
		return false;
	FuncExpression* fExpr = (FuncExpression*)expr;
	if(type != fExpr->type || name != fExpr->name)
		return false;
	for(unsigned int i=0;i<listArguments.size();i++)
	{
		if(!listArguments[i]->isEqual(fExpr->listArguments[i]))
		{
			return false;
		}
	}
	return true;
}

ListExpression::ListExpression(vector<LogicExpression*> _listArguments)
{
	type = 3;
	name = "";
	listArguments = _listArguments;
}
bool ListExpression::contain(LogicExpression* expr)
{
	for(int i=0;i<listArguments.size();i++)
	{
		if(listArguments[i]->contain(expr))
			return true;
	}
	return false;
}
LogicExpression* ListExpression::applySubstitute(Substitute* sub)
{

	vector<LogicExpression*> temp;
	ListExpression* newExpr = new ListExpression(temp);
	
	for(int i=0;i<listArguments.size();i++)
	{
		newExpr->listArguments.push_back( listArguments[i]->applySubstitute(sub));
	}
	return newExpr;
}
bool ListExpression::isEqual(LogicExpression* expr)
{
	if(!expr->isList())
		return false;
	ListExpression* fExpr = (ListExpression*)expr;
	if(type != fExpr->type || name != fExpr->name)
		return false;
	for(unsigned int i=0;i<listArguments.size();i++)
	{
		if(!listArguments[i]->isEqual(fExpr->listArguments[i]))
		{
			return false;
		}
	}
	return true;
}

LogicExpression* ListExpression::popFirst()
{
	
	LogicExpression* temp;
	if(listArguments.size()>0)
	{
		temp = listArguments[0];
		for(int i=0;i<listArguments.size()-1;i++)
		{
			listArguments[i] = listArguments[i+1];
		}
		listArguments.pop_back();
	}
	return temp;
}